#include "Task.h"


using namespace std;

void Task::initProgramDir()
{
	this->programDir = getDir();
}

void Task::run(const WCHAR* moduleName, WCHAR* parameter, WCHAR* dir) {
	BOOL ok = TRUE;
	HANDLE hStdInPipeRead = NULL;
	HANDLE hStdInPipeWrite = NULL;
	HANDLE hStdOutPipeRead = NULL;
	HANDLE hStdOutPipeWrite = NULL;

	// Create two pipes.
	SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
	ok = CreatePipe(&hStdInPipeRead, &hStdInPipeWrite, &sa, 0);
	if (ok == FALSE) return;
	ok = CreatePipe(&hStdOutPipeRead, &hStdOutPipeWrite, &sa, 0);
	if (ok == FALSE) return;

	STARTUPINFO si = { };
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESTDHANDLES;
	si.hStdError = hStdOutPipeWrite;
	si.hStdOutput = hStdOutPipeWrite;
	si.hStdInput = hStdInPipeRead;
	PROCESS_INFORMATION pi = { };


	//writeFile("gitLog.txt", "1");
	ok = CreateProcess(moduleName, parameter, NULL, NULL, TRUE, 0, NULL, dir, &si, &pi);
	if (ok == FALSE) return;

	// Close pipes we do not need.
	CloseHandle(hStdOutPipeWrite);
	CloseHandle(hStdInPipeRead);

	// The main loop for reading output from the DIR command.
	char buf[1024 + 1] = { };
	DWORD dwRead = 0;
	DWORD dwAvail = 0;
	string logs = "\n";
	try {
		BOOL ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
		while (ok == TRUE)
		{
			buf[dwRead] = '\0';
			logs += buf;
			puts(buf);
			ok = ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL);
		}
	}
	catch (...) {
		this->runLog.push_back("catch error at readFile");
	}


	this->runLog.push_back(logs);

	try {
		// Clean up and exit.
		CloseHandle(hStdOutPipeRead);
		CloseHandle(hStdInPipeWrite);

		WaitForSingleObject(pi.hProcess, INFINITE);

		CloseHandle(pi.hThread);
		CloseHandle(pi.hProcess);
	}
	catch (...) {
		this->runLog.push_back("catch error at close handle");
	}

}

void Task::readGitList()
{
	ifstream ifs;

	ifs.open((this->programDir + "gits.txt").c_str(), ios::in);

	if (!ifs.is_open()) {
		cout << "cannot open file" << endl;
		return;
	}

	char buf[1024] = { 0 };
	string txt = "";

	while (ifs >> buf)
	{
		txt += buf ;
		txt += +"\n";
	}

	ifs.close();

	gitList = split(txt, "\n");
}

vector<string> Task::split(string txt, string splitor)
{
	vector<string> strList;
	const char* arr = txt.c_str();
	size_t last = 0;
	size_t splitorLen = splitor.length();
	size_t len = txt.length();

	for (size_t i = 0; i < len; i++)
	{
		if (splitorLen + i > len) {
			break;
		}
		string cur = txt.substr(i, splitorLen);
		if (cur == splitor) {
			strList.push_back(txt.substr(last, i - last));
			i += splitorLen;
			last = i;
		}
	}

	strList.push_back(string(txt, last, len));

	return strList;
}

wchar_t* Task::charToWchar(const char* src)
{
	size_t size = strlen(src) + 1;
	wchar_t* dest = new wchar_t[size];
	size_t outSize;
	mbstowcs_s(&outSize, dest, size, src, size - 1);
	return dest;
}


Task::Task()
{
	this->initProgramDir();
	this->initGit(NULL);
	
	this->readGitList();
	size_t len = this->gitList.size();
	this->runLog.push_back("git list number: " + len);
	for (size_t i = 0; i < len; i++)
	{
		string el = this->gitList.at(i);
		if (el == "")continue;
		WCHAR* dir = this->charToWchar(el.c_str());
		this->runLog.push_back("update git: "+el);
		updateGit(dir);
	}
}

Task::~Task()
{
	string txt = "";
	for (size_t i = 0; i < this->runLog.size(); i++)
	{
		txt += this->runLog.at(i);
		txt += "\n";
	}

	writeFile("gitLog.txt", txt);
}

void Task::initGit(WCHAR* dir)
{
	LPWSTR moduleName = (LPWSTR)L"C:\\Windows\\System32\\cmd.exe";

	WCHAR parameter2[] = { L"/c whoami" };
	run(moduleName, parameter2, dir);
}

void Task::updateGit(WCHAR* dir) {

	LPWSTR moduleName = (LPWSTR)L"C:\\Windows\\System32\\cmd.exe";

	WCHAR parameter1[] = { L"/c git add ." };

	run(moduleName, parameter1, dir);

	WCHAR parameter2[] = { L"/c git commit -m \"update from cplusplus\"" };

	run(moduleName, parameter2, dir);

	WCHAR parameter3[] = { L"/c git push" };

	run(moduleName, parameter3, dir);
}

vector<string> Task::getGitList()
{
	return this->gitList;
}


void Task::writeFile(string path, string content)
{
	ofstream ofs;
	ofs.open((char*)(this->programDir + path).c_str(), ios::out);

	ofs << content << endl;

	ofs.close();
}